package cn.chiship.framework.business.biz.business.service.impl;

import cn.chiship.framework.common.util.TrustAllCertManager;
import cn.chiship.framework.docs.biz.service.FileResourcesService;
import cn.chiship.framework.docs.core.properties.FileUploadProperties;
import cn.chiship.sdk.cache.vo.CacheUserVO;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.base.ProgressResult;
import cn.chiship.sdk.core.enums.ProgressResultEnum;
import cn.chiship.sdk.core.exception.custom.BusinessException;
import cn.chiship.sdk.core.util.*;
import cn.chiship.sdk.core.util.excel.ExcelFactory;
import cn.chiship.sdk.core.util.excel.core.ExcelEnum;
import cn.chiship.sdk.core.util.excel.core.ExcelService;
import cn.chiship.sdk.core.util.http.ResponseUtil;
import cn.chiship.sdk.framework.base.BaseServiceImpl;
import cn.chiship.framework.business.biz.business.mapper.TestExampleMapper;
import cn.chiship.framework.business.biz.business.entity.TestExample;
import cn.chiship.framework.business.biz.business.entity.TestExampleExample;
import cn.chiship.framework.business.biz.business.service.TestExampleService;
import cn.chiship.sdk.framework.pojo.dto.export.ExportDto;
import cn.chiship.sdk.framework.pojo.dto.export.ExportTransferDataDto;
import cn.chiship.sdk.framework.pojo.dto.export.ImportDto;
import cn.chiship.sdk.framework.pojo.vo.UploadVo;
import cn.chiship.sdk.framework.properties.ChishipDefaultProperties;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.IOUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * 示例（正式环境可删除）业务接口实现层 2022/9/15
 *
 * @author lijian
 */
@Service
public class TestExampleServiceImpl extends BaseServiceImpl<TestExample, TestExampleExample>
        implements TestExampleService {

    private static final Logger LOGGER = LoggerFactory.getLogger(TestExampleServiceImpl.class);

    @Resource
    TestExampleMapper testExampleMapper;

    @Resource
    FileUploadProperties fileUploadProperties;

    @Resource
    FileResourcesService fileResourcesService;

    @Resource
    ChishipDefaultProperties chishipDefaultProperties;

    String fileName = "测试示例";

    String sheetName = "测试示例";

    String sheetTitle = "测试示例明细";

    @Override
    public BaseResult insertSelective(TestExample testExample) {
        testExample.setFullPinyin(ChineseCharToEn.getAllFirstLetters(testExample.getName()).toUpperCase());
        testExample.setFirstLetter(ChineseCharToEn.getFirstLetter(testExample.getName()).toUpperCase());
        return super.insertSelective(testExample);
    }

    @Override
    public void generatePdf(String id, HttpServletResponse response) throws Exception {
        TestExample testExample = testExampleMapper.selectByPrimaryKey(id);

        String content = "暂无介绍";
        TrustManager[] trustManagers = new TrustManager[]{new TrustAllCertManager()};
        SSLContext sslContext = null;
        sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustManagers, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        Document document = Jsoup.connect("https://baike.baidu.com/item/" + testExample.getName()).get();
        Elements elements = document.getElementsByClass("lemmaSummary_ISuoh");
        if (!elements.isEmpty()) {
            content = elements.get(0).text();
        }

        Map<String, Object> reportData = new HashMap<>(7);
        reportData.put(PdfUtil.PDF_TEMPLATE_FIELD_TYPE_TEXT + "regionName", testExample.getName());
        reportData.put(PdfUtil.PDF_TEMPLATE_FIELD_TYPE_TEXT + "firstLetter", testExample.getFirstLetter());
        reportData.put(PdfUtil.PDF_TEMPLATE_FIELD_TYPE_TEXT + "adCode", testExample.getAdCode());
        reportData.put(PdfUtil.PDF_TEMPLATE_FIELD_TYPE_TEXT + "fullPingYin", testExample.getFullPinyin());
        reportData.put(PdfUtil.PDF_TEMPLATE_FIELD_TYPE_TEXT + "remrk", content);

        reportData.put(PdfUtil.PDF_TEMPLATE_FIELD_TYPE_IMAGE + "image",
                ImageUtil.getImgByteByUrl("https://cdn-chiship.oss-cn-beijing.aliyuncs.com/default/testPdfImage.png"));
        reportData.put(PdfUtil.PDF_TEMPLATE_FIELD_TYPE_TEXT + "fillDate", DateUtils.getTime());
        byte[] bytes = PdfUtil.generalPdfByTemplateInput(
                FileUtil.downLoadToByte("https://cdn-chiship.oss-cn-beijing.aliyuncs.com/default/pdfTemplate.pdf"),
                reportData);
        ResponseUtil.setAttachmentResponseHeader(response, testExample.getName() + "简介.pdf");
        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");

        IOUtils.write(bytes, response.getOutputStream());
    }

    @Override
    public void generateWord(String id, HttpServletResponse response) throws Exception {
        /**
         * 若是有图片资源，模板必须是doc编写转换xml
         */
        TestExample testExample = testExampleMapper.selectByPrimaryKey(id);

        String content = "暂无介绍";
        TrustManager[] trustManagers = new TrustManager[]{new TrustAllCertManager()};
        SSLContext sslContext = null;
        sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustManagers, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        Document document = Jsoup.connect("https://baike.baidu.com/item/" + testExample.getName()).get();
        Elements elements = document.getElementsByClass("lemmaSummary_ISuoh");
        if (!elements.isEmpty()) {
            content = elements.get(0).text();
        }
        Map<String, String> templateParam = new HashMap<>(5);
        templateParam.put("date", DateUtils.getDate());
        templateParam.put("name", testExample.getName());
        templateParam.put("code", testExample.getAdCode());
        templateParam.put("simple", testExample.getFirstLetter());
        templateParam.put("full", testExample.getFullPinyin());
        templateParam.put("remark", content);
        templateParam.put("imageBase64", ImageUtil.getImgBase64ByUrl("https://cdn-chiship.oss-cn-beijing.aliyuncs.com/default/testPdfImage.png"));

        try {
            response.setContentType("application/msword");
            response.setCharacterEncoding("utf-8");
            ResponseUtil.setAttachmentResponseHeader(response, testExample.getName() + "简介.docx");
            Configuration configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
            configuration.setDefaultEncoding("utf-8");
            configuration.setTemplateLoader(new ClassTemplateLoader(getClass(), "/templates"));
            Template t = configuration.getTemplate("wordTemplate.xml", "utf-8");
            Writer out = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), StandardCharsets.UTF_8), 10240);
            t.process(templateParam, out);
            out.close();
        } catch (Exception e) {
            throw new BusinessException("生成Word文档异常，异常原因：" + e.getMessage());
        }
    }

    @Override
    public ExportTransferDataDto assemblyExportData(ExportDto exportDto) {
        List<String> labels = new ArrayList<>();
        List<List<String>> valueList = new ArrayList<>();
        int total = 0;
        labels.add("编号");
        labels.add("名称");
        labels.add("全拼");
        labels.add("首字母");
        labels.add("区域代码");
        labels.add("新增时间");
        labels.add("最后修改时间");

        TestExampleExample testExampleExample = new TestExampleExample();
        List<TestExample> testExamples = testExampleMapper.selectByExample(testExampleExample);

        for (TestExample testExample : testExamples) {
            List<String> values = new ArrayList<>();
            values.add(testExample.getId());
            values.add(testExample.getName());
            values.add(testExample.getFullPinyin());
            values.add(testExample.getFirstLetter());
            values.add(testExample.getAdCode());
            values.add(DateUtils.dateTime(testExample.getGmtCreated()));
            values.add(DateUtils.dateTime(testExample.getGmtModified()));
            valueList.add(values);
        }

        total = testExamples.size();
        return new ExportTransferDataDto(fileName, sheetName, sheetTitle, labels, valueList, total);
    }

    @Override
    public ExportTransferDataDto downloadTemplate(String exportType) {
        List<String> headerNames = new ArrayList<>();
        List<List<String>> rows = new ArrayList<>();
        headerNames.add("名称");
        headerNames.add("区域代码");
        List<String> values = new ArrayList<>();
        values.add("示例名称");
        values.add("示例代码");
        rows.add(values);
        ExcelService excelService = ExcelFactory.getExcelService(ExcelEnum.getExcelEnum(exportType));
        excelService.writeExcel("模板", "标题", 1, headerNames, rows);
        headerNames = new ArrayList<>();
        rows = new ArrayList<>();
        headerNames.add("备注");
        headerNames.add("说明");
        values = new ArrayList<>();
        values.add("示例数据1");
        values.add("示例数据2");
        rows.add(values);
        excelService.writeExcel("说明", "模板说明", 2, headerNames, rows);
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        excelService.writeAndClose(os);
        return new ExportTransferDataDto("测试数据导入模板", os.toByteArray(), exportType);
    }

    @Override
    public void assemblyImportData(String taskId, ExcelService excelService, ImportDto importDto) {
        InputStream inputStream;
        try {
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM));
            Thread.sleep(1000);
            if (Boolean.TRUE.equals(importDto.getSave())) {
                inputStream = excelService.getInputStream();
                String catalogId = chishipDefaultProperties.getImportDataCatalog();
                processStatusHm.put(taskId,
                        ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "您开启了保留源文件，正在保存源文件..."));
                Thread.sleep(1000);
                if (StringUtil.isNullOrEmpty(fileUploadProperties.getFilePathByCatalogId(catalogId))) {
                    processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM,
                            "您还未配置【chiship.importData.catalogId】属性或catalogId不存在"));
                }
                processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "源文件保存中..."));
                CacheUserVO cacheUserVO = importDto.getCacheUserVO();
                BaseResult baseResult = fileResourcesService.uploadFile(inputStream, catalogId,
                        importDto.getFileName(), importDto.getContentType(), cacheUserVO);
                if (baseResult.isSuccess()) {
                    UploadVo uploadVo = (UploadVo) baseResult.getData();
                    processStatusHm.put(taskId,
                            ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM,
                                    String.format("源文件保存成功,明细如下【文件名：%s，唯一标识：%s】", uploadVo.getOriginalName(),
                                            uploadVo.getUuid())));
                    Thread.sleep(1000);
                    processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOWN_ENUM,
                            String.format(uploadVo.getUuid())));
                    Thread.sleep(1000);
                } else {
                    processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM,
                            baseResult.getData().toString()));
                    return;
                }
            } else {
                processStatusHm.put(taskId,
                        ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "您开启了不保留源文件..."));
            }
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM));

            Map<String, String> headerTitleMap = new LinkedHashMap<>();
            headerTitleMap.put("name", "名称");
            headerTitleMap.put("adCode", "区域代码");
            BaseResult baseResult = excelService.readExcel(1, 3, 4, headerTitleMap);
            if (!baseResult.isSuccess()) {
                processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM,
                        "解析出错：" + baseResult.getData().toString()));
                return;
            }
            ArrayList<Map<String, String>> dataResult = (ArrayList) baseResult.getData();

            processStatusHm.put(taskId,
                    ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "解析出" + dataResult.size() + "条数据！"));
            Thread.sleep(1000);
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "数据正在比对入库中..."));
            int finishCount = 0;
            for (Map<String, String> map : dataResult) {
                String name = map.get("name");
                String adCode = map.get("adCode");
                TestExample testExample = new TestExample();
                testExample.setName(name);
                testExample.setAdCode(adCode);
                Double progressValue = Double.parseDouble(StringUtil.formatPercent(finishCount++, dataResult.size()));
                processStatusHm.put(taskId, ProgressResult.out(progressValue, "解析出" + dataResult.size() + "条数据！已完成：" + progressValue + "%！"));
                Thread.sleep(10);
            }
            processStatusHm.put(taskId, ProgressResult.out(100D, "已完成：100%！"));
            //此行代码解决 进度不满100%时先睡眠1秒 强制更到100%
            Thread.sleep(1000);
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_FINISH_ENUM, "入库完成！"));
        } catch (Exception e) {
            e.printStackTrace();
            processStatusHm.put(taskId,
                    ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM, e.getLocalizedMessage()));
        }
    }

}
